<template>
  <div class="title">
    <h1>{{ msg }}</h1>
    <!-- 写在组件标签<Student>上的@事件或者属性，其实都会透传到组件的根标签上，所以实际上是给Student组件实例(vc)绑定的 
      因为，<student></student>，Vue解析时会帮我们创建student组件的实例对象-->
    <!-- 由于v-on在student这个组件标签上，所以说给student这个组件的实例对象vc身上绑定了一个事件，事件名叫atguigu，如果以后有人触发的这个事件，那么getStudentName函数就会被调用 -->

    <!-- 通过父组件给子组件绑定一个自定义事件实现:子给父传递数据(一法用@或者v-on)-->
    <!-- <Student v-on:atguigu="getStudentName" /> -->
    <!-- <Student v-on:atguigu.once="getStudentName" /> (事件只触发一次) -->

    <!-- 通过父组件给子组件绑定一个自定义事件实现:子给父传递数据(二法用ref)-->
    <!-- 通过this.$refs.student拿到student的vc,再通过$on绑定自定义事件 -->
    <Student ref="student" />

    <hr />
    <!-- 通过父组件给子组件传递函数类型的props实现:子给父传递数据-->
    <School :getSchoolName="getSchoolName" @click.native="show" />

    <!-- 若给组件绑定原生dom事件(click)，会全部都变成自定义事件，原生事件失效了 
    若加上事件修饰符native，就会被当为原生dom事件处理,将此事件交给对应组件的template中最外层的那个html标签上(根标签)-->
  </div>
</template>


<script>
import School from "./components/School.vue";
import Student from "./components/Student.vue";

export default {
  name: "App",
  components: {
    Student,
    School,
  },
  data() {
    return {
      msg: "hello",
    };
  },
  methods: {
    getSchoolName(name) {
      console.log(`App收到了学校名${name}`);
    },
    getStudentName(name, ...rest) {
      //剩余参数，rest为数组
      console.log(`App收到了学生名${name}与${rest}`);
    },
    show() {
      alert(123);
    },
  },
  //当App组件挂载完毕时触发
  mounted() {
    this.$refs.student.$on("atguigu", this.getStudentName); //绑定自定义事件

    /* this.$refs.student.$once("atguigu", this.getStudentName)(事件只触发一次); */

    /* ------------------------------------------------------------- */
    /* this.$refs.student.$on("atguigu", function (name, ...rest) {
      console.log(`App收到了学生名${name}与${rest}`);
      console.log(this);//这么写this为student组件实例对象，用箭头函数可以解决这个问题
    }); */
  },
};

/*
## 组件的自定义事件

1. 一种组件间通信的方式，适用于：<strong style="color:red">子组件 ===> 父组件</strong>

2. 使用场景：A是父组件，B是子组件，B想给A传数据，那么就要在A中给B绑定自定义事件（<span style="color:red">事件的回调在A中</span>）。

3. 绑定自定义事件：

    1. 第一种方式，在父组件中：```<Demo @atguigu="test"/>```  或 ```<Demo v-on:atguigu="test"/>```

    2. 第二种方式，在父组件中：

        ```js
        <Demo ref="demo"/>
        ......
        mounted(){
           this.$refs.xxx.$on('atguigu',this.test)
        }
        ```

    3. 若想让自定义事件只能触发一次，可以使用```once```修饰符，或```$once```方法。

4. 触发自定义事件：```this.$emit('atguigu',数据)```		

5. 解绑自定义事件```this.$off('atguigu')```

6. 组件上也可以绑定原生DOM事件，需要使用```native```修饰符。

7. 注意：通过```this.$refs.xxx.$on('atguigu',回调)```绑定自定义事件时，回调<span style="color:red">要么配置在methods中</span>，<span style="color:red">要么用箭头函数</span>，否则this指向会出问题！ 
 */
</script>

<style>
.title {
  background-color: gray;
  padding: 10px;
}
</style>

 